Components contain metadata at the top and exported classed on the bottom. Example:
@Component({ selector: 'app-root', template: '<app-position></app-position>', styleUrls: ['./app.component.css'] }) export class AppComponent { private jobPosition = "CEO"; hidePosition = false; getData() { return this.jobPosition; } }
Selectors
The selector defines how a component is added to an HTML page / template. For example:
selector: ‘app-root’
The custom tags need to be shown. If a selector has dot (.) then it is referred as class:
Selector: ‘.app-root’
Selector: ‘[app-root]’
Templates
Using the “template” keyword means you put the markup inside it as a string
template: ‘<html…>’
But the templateUrl refers to an html file
template: ‘./template.html’
Styles
Make sure to include the style inside brackets as shown in the example above.
Interpolation
Interpolation is done through curly brackets – {{ xxx }}
The angular compiler will interpret these during run time.
<h1>{{ somevariable }}</h1>
The variables between a component and it’s template are tightly coupled and template can access anything above private variables.
You can also execute some js code inside the interpolations. But it is only read only, for example
<h1>{{ “Job: “ + jobvariable }}</h1>
Also note that inside the interpolation brackets you cannot access the global JavaScript object. For example:
{{ window.location.href }} this will error
Note that templates cannot have javascript code that accesses the JavaScript Global Object.
Property Binding
Angular compiler can process attributes so it’s encouraged to use these. For example
<button disabled></button>
For angular to be able to modify the attributes, put brackets around them.
<button [disabled]=’somevariable’></button> <button bind-disabled=’somevariable’></button>
This is how angular does property binding.
Event Binding
Event bindings are done using the parenthesis.
<button (click)=’onclickmethod()’></button>
Event bindings can also send parameters. The $event variable is a special variable recognized by the angular compiler and it passes the event object.
<button (click)=’onclickmethod($event)’></button>
You could put the code directly in the html to have it run the code inline instead of referencing back to the component file.
Classes, Styles and Attributes
We can bind css classes to an html tag using the property binding syntax.
<div [class]=”myvar”></div> ... myvar = “text-danger”
You can also bind to special keyword [ngClass] which is similar to above
<div [ngClass]=’myvar’></div> ... myvar = { “text-danger”: false, “text-success”: true }
The example above will show true.
Finally – event binding using property binding can be for specific css property. In the example below, the text-danger css class is loaded if the result of myvar is true
<div [class.text-danger]=’myvar’></div>
When applying in-line styles, we can set a global-component level style by using the keyword “:host”. Example
styles: [`:host { color: red; }`]
Also note that styles are only applied to the current component, it doesn’t go up to parents or children. However, if you do want to apply to children under the component, use the keyword “/deep/”
Template Reference Variables
To reference elements in a template we can put a variable definition on it using hash.
<input #name placeholder="name"> <button (click)="username = name.value">Update</button> {{ username }}
In the example above, by clicking on the update button the username variable gets set to the value of the #name input element.
ngIf, ngFor, ngSwitch
The expression below will not be added to the DOM during the angular compile.
<p *ngIf="false">lorem ipsum</p>
The condition can reference a variable as well instead of literal.
To do else conditions, use the “else” keyword and reference an element reference variable
<p *ngIf="false; else myblock">this will not display</p> <ng-template #myblock> <p>this will be displayed instead</p> </ng-template>
We can write complete if – then – else blocks as follows
<p *ngIf="false; then thenBlock else elseblock">this will not display</p> <ng-template #thenblock> <p>this will not display</p> </ng-template> <ng-template #elseblock> <p>this will be displayed instead</p> </ng-template>
In the example above the “thenBlock” displays only when the condition is true.
For blocks are structured as such. It can be used with or without the index elements of the loop. Also note that there special keywords like “first” and “last” that Angular uses to get the first and last elements of the array. Other keywords are “even”, “odd” etc.
<div *ngFor="let p of positions; index as i; first as f; even as e"> <p>{{ p.title }} {{ i }} {{ f }} {{ e }}</p> </div>
The above could display something like:
title1 0 true true title2 1 false false title3 2 false true
The Switch statement is similar to the ngIf and is structured as follows.
<div [ngSwitch]="positions.length"> <div *ngSwitchCase="1">One</div> <div *ngSwitchCase="2">Two</div> <div *ngSwitchDefault>Default</div> </div>
Two-way Binding
Two way binding is done using ngModels. The syntax is the banana-in-box – [( xxx )]
<input [(ngModel)] = "name"> {{ name }}
Note that in order to do two-way binding we must include the FormsModule in the component or module.
Component Communication
There are input and output decorators for components to communicate with it’s parents and children. To accept variables, we use Input as follows:
export class PositionComponent { @Input() title: string; }
Now when calling the PositionComponent we would pass in the title string as part of the element’s property:
<position [title]="Some Title Here"></position>
<position title="Some Title Here"></position> ... export class PositionComponent { @Input('title') internalTitle: string; }
<position (eventFromChild)="onEventFromChild($event)"></position> ... export class ChildComponent { @Output() thisEvent = new EventEmitter<null>(); onSomeClick() { this.thisEvent.emit(); // bubbles the thisEvent variable up to the parent } }
Content Projection / Transclusion
This is the inclusion of a content from one component into another component. This is done through a keyword tag – <ng-content></ng-content> In the example below, we are being selective in what part of the parent’s call to the position component is to be displayed in the position component.
<position title = "title1"> <p class = "copyright" >Copyright 2017</p> <p>Lorem Ipsum</p> </position> ... <ng-content select=".copyright"></ng-content>
In the example above, the position child component would only be displaying the “Copyright 2017” paragraph which i got from its parent. It will not display the second paragraph with “lorem ipsum”. The following examples also shows how we can select based on element type and how to not select a specific class.
<ng-content select="p"></ng-content> <ng-content select=":not(.copyright)"></ng-content>
Field Decorators
There is a field decorator “@HostBinding” that can be set inside a component to add or remove classes to the component. The example below also shows using a “@HostListener” so that it captures any mouse clicks on the page.
export class Example1Component { @HostBinding('class.text-danger') redText = true; @HostListener('click', ['$event']) onclick(event) { // do something here } }
The “@ViewChild” field decorator allows template reference variable. In the example below, we can access the <position> element from the component class by setting it to the @ViewChild variable.
<position #myposition></position> ... export class ExampleComponent { @ViewChild(PositionComponent) position: PositionComponent; // can reference the child component through the 'position' variable }
If our component had reference the position child component several times, we can use the ‘@ViewChildern’ field decorator to reference the list. Note that this requires use of keyword QueryList, which is a list of the components.
@ViewChildren(PositionComponent) positions: QueryList<PositionComponent>;
The opposite of using @ViewChildren field decorators are the @ContentChild and @ContentChildren field decorators. These are used to reference the <ng-content> elements. So in the template example below, we would use @ViewChild to access the <position> elements and @ContentChild to access the <ng-content> element.
<position title='CFO'></position> <position title='CIO'></position> <position title='CTO'></position> <ng-content></ng-content>
Component Lifecycle Hooks
Some common lifecycle hooks that can be used in components are shown below in the order of which they fire when loading a page.
- constructor() – does DI
- ngOnChanges() – handles input properties
- ngOnInit() – all input properties initialized
- ngDoCheck() – when an input property is changed
- ngAfterContentInit() – when component content is initialized
- ngAfterContentChecked() – content checked and initialized
- ngAfterViewInit() – components view is to be initialized
- ngAfterViewChecked() – when a view is checked
- ngOnDestroy() – called right before instance is destroyed